package packing;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Scanner;

import common.CatAndPoints;
import common.SQLCall;

/**
 * Given an Exam object, create all document files related to the exam. This
 * include the exam and jar instruction for students, and the grade sheet for
 * faculty.
 * 
 */
public class Documentation
{
	static final String DATE = "DateHere";
	static final String INSTRUCTION = "InstructionsHere";
	static final String NUM_END = "NumEnd";
	static final String PART = "Part ";
	static final String JAR_FILE_NAME = "jar_instructions.html";
	static final String INST_FILE_NAME = "exam_instructions.html";
	static final String SCORE_SHEET = "ProgExamScoreSheetDateHere.html";
	static final String CURRENT_ID = "CurrentID";

	static final String STUDENT_PATH = "/tmp/ape/Student/";
	static final String SOLUTION_PATH = "/tmp/ape/Solution/";

	private Connection conn;

	public Documentation(Connection c)
	{
		conn = c;
	}

	/**
	 * Grab exam instructions from database. It will modify some fields(date,
	 * instructions) that are needed to be changed from time to time.
	 * 
	 * @param exam
	 *            Exam that holds question id that is used for current exam
	 * @param date
	 *            scheduled date for current exam
	 */
	public void generateInstruction(Exam exam, String date)
	{
		try
		{
			PreparedStatement stmt = conn.prepareStatement(
					"select * FROM DOCUMENTS where DOCUMENT_NAME=?");
			stmt.setString(1, INST_FILE_NAME);
			ResultSet rset = stmt.executeQuery();

			rset.next();
			Scanner inFile = new Scanner(
					rset.getBinaryStream("DOCUMENT_FILE"));

			PrintWriter outFile = new PrintWriter(new File(STUDENT_PATH,
					INST_FILE_NAME));

			while (inFile.hasNext())
			{
				String s = inFile.nextLine();
				if (s.contains(DATE))
				{
					s = s.replace(DATE, date);
				} else if (s.contains(NUM_END))
				{
					s = s.replace(NUM_END, ((Integer) exam.size()).toString());
				} else if (s.contains(INSTRUCTION))
				{
					s = "";
					int i = 1;
					while (exam.hasNext())
					{
						s += "<li><u>" + PART + i++ + "</u>:&nbsp;&nbsp;";
						s += readInstruction(exam.next());
						s += "</li><br><br>";
					}
				}
				outFile.println(s);
			}
			inFile.close();
			outFile.close();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * Grab score sheet from database. It will modify grading criteria that are
	 * needed to be changed from time to time.
	 * 
	 * @param exam
	 *            current Exam
	 * @throws SQLException 
	 * @throws FileNotFoundException 
	 */
	public void generateGradesheet(Exam exam, String date) 
	throws SQLException, FileNotFoundException
	{
		CatAndPoints qCategory = SQLCall.getCategoryList(conn);

		String fileName = SCORE_SHEET.replace(DATE, date);
		PrintWriter outFile = new PrintWriter(new File(SOLUTION_PATH,
				fileName));

		// put header
		outFile.println("<html><head><title>Program Exam Score Sheet ");
		outFile.println(date + "</title></head>");

		// put body
		outFile.println("<body><font face=\"Times\">");
		outFile.println("<CAPTION align=\"left\">Test ID #:&nbsp;&nbsp;"
				+ exam.examID + "</CAPTION>");
		outFile.println("<table border=\"1\" cellpadding=\"0\" " +
				"cellspacing=\"0\" bordercolor=\"black\">");

		// start table
		outFile.println("<tr height=\"30\">");
		outFile.println("<th>Category</th><th>Scoring Criteria</th>" +
						"<th>Comments</th><th>Score</th>");
		outFile.println("</tr>");
		// put category from database
		for (int cat : qCategory)
		{
			outFile.println("<tr>");
			outFile.println("<td width=\"135\">");
			outFile.println(qCategory.getDescription(cat) + "<br><br>");
			outFile.println(qCategory.getPoints(cat) + " Points total</td>");
			outFile.println("<td width=\"370\">");
			exam.reset();
			while (exam.hasNext())
			{
				Question question = exam.next();
				if (cat == question.type)
				{
					outFile.println("<b>" + question.title + "("
							+ question.points
							+ " points possible):</b>&nbsp&nbsp");
					outFile.println(new String(question.getCriteria()
							.getByteArray()));
					outFile.println("<br><br>");
				}
			}
			outFile.println("</td>");
			outFile.println("<td width=\"145\">&nbsp</td>");
			outFile.println("<td width=\"60\">&nbsp</td>");
			outFile.println("</tr>");
		}
		// end of table
		outFile.println("<tr height=\"30\">");
		outFile.println("<td><i><b>Total: 100</b></i></td>");
		outFile.println("<td><i><b>Passing Score: 80</b></i></td>");
		outFile.println("<td>&nbsp</td><td>&nbsp</td></tr></table>");
		// put footer
		outFile.println("</font></body></html>");

		outFile.close();
	}

	/**
	 * Grab instructions from database. Bold the keywords by source file names
	 * 
	 * @param question
	 *            A Question object holding information about a specific
	 *            question
	 */
	public String readInstruction(Question question) throws SQLException
	{
		String instruction = "";
		ArrayList<String> keywords = new ArrayList<String>();

		SourceFile f = question.getInstructions();
		instruction = new String(f.getByteArray());

		question.setIterator(Question.PROBLEM);

		keywords.add(question.title);
		while (question.hasNext())
		{
			f = question.next();
			String[] temp = f.name.split("\\.");
			keywords.add(temp[0]);

		}
		for (String keyword : keywords)
		{
			if (instruction.contains(keyword))
				instruction = instruction.replace(keyword, "<b>" + keyword
						+ "</b>");
		}
		return instruction;
	}

	/**
	 * Grab jar file instruction from database. It will not change any content
	 * of the file.
	 */
	public void generateJar()
	{
		try
		{
			PreparedStatement stmt = conn.prepareStatement(
					"select * FROM DOCUMENTS where DOCUMENT_NAME=?");
			stmt.setString(1, JAR_FILE_NAME);
			ResultSet rset = stmt.executeQuery();

			// read it as blob and just spit out to html because there is
			// nothing to change
			rset.next();
			Blob b = rset.getBlob("DOCUMENT_FILE");
			BufferedOutputStream os = new BufferedOutputStream(
					new FileOutputStream(
							new File(STUDENT_PATH, JAR_FILE_NAME)));
			os.write(b.getBytes(1, (int) b.length()), 0, (int) b.length());
			os.flush();
			os.close();

			stmt.close();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}
